import threading
import queue
import cv2
import base64
import json
import logging
from collections import Counter
import websocket

# 配置 logging 模块，将日志记录保存到文件中
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='velocity.log',  # 日志文件名
    filemode='w'  # 写入模式，'w' 表示覆盖写入，'a' 表示追加写入
)

cloud_uri = "ws://202.114.212.194:50511/detect"
cloud_speech_uri = "ws://202.114.212.194:50512/audio"
front_video_uri = "ws://10.12.48.113:7979"
front_status_uri = "ws://10.12.48.113:6868"
window_size = 30
step = 10

test_video = "D:\\CS_COURSE\\SoftwareEngineering\\Test\\velocity.mp4"

def save_image(buffer, filename):
    with open(filename, "wb") as f:
        f.write(buffer)

def capture_camera(queue1, queue2):
    while True:
        cap = cv2.VideoCapture(test_video)
        try:
            while cap.isOpened():
                ret, frame = cap.read()
                if not ret:
                    logging.error("Failed to read frame")
                    break

                # 编码图片为 Base64
                _, buffer = cv2.imencode('.jpg', frame)
                img_str = base64.b64encode(buffer)
                queue1.put(img_str)
                queue2.put(img_str)
                threading.Event().wait(0.01)  # 主动交出控制权，避免阻塞
        finally:
            cap.release()
            logging.info("Video capture finished")

def video_websocket(URI, queue, send_queue=None):
    key = "cloud" if URI == cloud_uri else "front"
    window = []
    logging.info(f"Connecting to {key}")
    try:
        ws = websocket.create_connection(URI)
        while True:
            img_str = queue.get()  # 从队列中获取图片数据
            try:
                if URI == cloud_uri:
                    print("send image to cloud")
                    img_bytes = base64.b64decode(img_str)
                    save_image(img_bytes, "test.jpg")
                    ws.send(img_str)
                else:
                    ws.send(img_str)
                logging.info(f"Sent image to {key}")
            except Exception as e:
                logging.error(f"Failed to send image to {key} : {e}")
                continue

            if URI == cloud_uri:
                # 接收服务器返回的推理结果
                response = ws.recv()
                logging.debug(f"Received raw response from cloud: {response}")
                if response:
                    try:
                        result = json.loads(response)
                        window.append(result['detected_class'])
                        logging.info(f"Received result from cloud: {result['detected_class']}")
                        if len(window) == window_size:
                            counter = Counter(window)
                            most_common, _ = counter.most_common(1)[0]
                            if send_queue:
                                send_queue.put(most_common)  # 将结果放入队列
                            logging.info(f"Sent result to status: {most_common}")
                            window = window[step:]
                    except json.JSONDecodeError as e:
                        logging.error(f"Failed to decode JSON response from cloud: {e}")
                else:
                    logging.error("Received empty response from cloud")
    except websocket.WebSocketConnectionClosedException:
        logging.warning(f"Connection to {key} closed")
    except Exception as e:
        logging.error(f"Failed to connect to {key} : {e}")

def status_websocket(URI, queue):
    key = "status"
    logging.info(f"Connecting to {key}")
    try:
        ws = websocket.create_connection(URI)
        while True:
            status = queue.get()
            ws.send(str(status))
    except Exception as e:
        logging.error(f"Failed to connect to {key} : {e}")

def main():
    queue_cloud = queue.Queue(maxsize=10)
    queue_front = queue.Queue(maxsize=10)
    queue_status = queue.Queue(maxsize=10)


    threads = [
        threading.Thread(target=capture_camera, args=(queue_cloud, queue_front)),
        threading.Thread(target=video_websocket, args=(front_video_uri, queue_front)),
        threading.Thread(target=video_websocket, args=(cloud_uri, queue_cloud, queue_status)),
        threading.Thread(target=status_websocket, args=(front_status_uri, queue_status))
    ]

    for thread in threads:
        thread.start()

    for thread in threads:
        thread.join()

if __name__ == "__main__":
    main()